package com.authine.cloudpivot.ext.asyncTask;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.authine.cloudpivot.ext.domain.DeptUser;
import com.authine.cloudpivot.ext.domain.HOrgDepartment;
import com.authine.cloudpivot.ext.domain.HOrgDeptUser;
import com.authine.cloudpivot.ext.domain.HOrgRole;
import com.authine.cloudpivot.ext.domain.HOrgRoleUser;
import com.authine.cloudpivot.ext.domain.HOrgUser;
import com.authine.cloudpivot.ext.domain.Role;
import com.authine.cloudpivot.ext.domain.UserDetail;
import com.authine.cloudpivot.ext.mapper.HOrgDepartmentMapper;
import com.authine.cloudpivot.ext.mapper.HOrgDeptUserMapper;
import com.authine.cloudpivot.ext.mapper.HOrgRoleMapper;
import com.authine.cloudpivot.ext.mapper.HOrgRoleUserMapper;
import com.authine.cloudpivot.ext.mapper.HOrgUserMapper;
import com.authine.cloudpivot.ext.util.SynUserUtil;
import com.dingtalk.api.DefaultDingTalkClient;
import com.dingtalk.api.DingTalkClient;
import com.dingtalk.api.request.OapiGettokenRequest;
import com.dingtalk.api.request.OapiIndustryUserListRequest;
import com.dingtalk.api.request.OapiV2UserGetRequest;
import com.dingtalk.api.response.OapiGettokenResponse;
import com.dingtalk.api.response.OapiIndustryUserListResponse;
import com.dingtalk.api.response.OapiV2UserGetResponse;
import com.google.common.collect.Lists;
import com.taobao.api.ApiException;

import lombok.extern.slf4j.Slf4j;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;

/**
 * @author liujing
 * @version 1.0.0
 * @Date: 2021/6/17
 */
@Component
@Slf4j
public class AsyncTask {

    @Autowired
    private HOrgDepartmentMapper hOrgDepartmentMapper;
    @Autowired
    private HOrgUserMapper hOrgUserMapper;
    @Autowired
    private HOrgRoleUserMapper hOrgRoleUserMapper;
    @Autowired
    private HOrgDeptUserMapper hOrgDeptUserMapper;
    @Autowired
    private HOrgRoleMapper hOrgRoleMapper;
    private static final String PASSWORD = "{bcrypt}$2a$10$NvgvcocBqMn050z4nC0I6OeAhO5ERjM74pvMtSGLghPhWI5ed5myG";// 密码
    // 123456
    private static final String STATUS = "ENABLE";// 是否启用
    private static final String GENDER = "OTHER";// 性别
    private static final String UNITTYPE = "USER";

    @Async("taskExecutor")
    public void getUserByOneDept(String deptId, String appkey, String appsecret)
        throws ApiException, BadHanyuPinyinOutputFormatCombination {
        long currentTimeMillis = System.currentTimeMillis();
        HOrgDepartment hOrgDepartment = hOrgDepartmentMapper.selectByPrimaryKey(deptId);
        String deptSourceId = hOrgDepartment.getSourceid();
        String corpId = hOrgDepartment.getCorpid();
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/industry/user/list");
        OapiIndustryUserListRequest req = new OapiIndustryUserListRequest();
        req.setCursor(1L);
        List<JSONObject> results = Lists.newArrayList();
        List<JSONObject> list = getList(true, results, deptSourceId, req, client, appkey, appsecret);
        if (CollectionUtils.isEmpty(list)) {
            return;
        }
        List<HOrgUser> hOrgUsers = new ArrayList<>();
        List<HOrgRoleUser> hOrgRoleUsers = new ArrayList<>();
        List<HOrgDeptUser> hOrgDeptUsers = new ArrayList<>();
        for (JSONObject object : list) {
            DeptUser deptUser = JSON.toJavaObject(object, DeptUser.class);
            // h_org_user
            String ysUserId = SynUserUtil.getUUID();
            Long ysUserSortKey = hOrgUserMapper.getMaxSortkey() + 1;
            HOrgUser hOrgUser = new HOrgUser();
            UserDetail userDetail = getUserDetail(deptUser.getUserid(), appkey, appsecret);
            if (null == userDetail) {
                return;
            }
            hOrgUser.setActive(userDetail.getActive());
            hOrgUser.setAdmin(userDetail.getAdmin());
            hOrgUser.setAppellation(null);
            hOrgUser.setBirthday(null);
            hOrgUser.setBoss(userDetail.getBoss());
            // 取corpId
            // String unionEmpExt = userDetail.getUnionEmpExt();
            // JSONObject jo =JSONObject.parseObject(unionEmpExt);
            hOrgUser.setCorpid(corpId);
            hOrgUser.setCreatedtime(new Date());
            hOrgUser.setCreater(null);
            hOrgUser.setDeleted(false);
            hOrgUser.setDepartmentid(deptId);
            hOrgUser.setDeparturedate(null);
            hOrgUser.setDingtalkid(null);
            hOrgUser.setDinguserjson(null);
            hOrgUser.setEmail(userDetail.getEmail());
            hOrgUser.setEnabled(true);
            hOrgUser.setEmployeeno(null);
            hOrgUser.setEntrydate(new Date(userDetail.getHired_date()));
            hOrgUser.setEmployeerank(null);
            hOrgUser.setGender(GENDER);
            hOrgUser.setId(ysUserId);
            hOrgUser.setIdentityno(null);
            hOrgUser.setImgurl(userDetail.getAvatar());
            hOrgUser.setImgurlid(null);
            hOrgUser.setLeader(false);
            hOrgUser.setManagerid(null);
            hOrgUser.setMobile(userDetail.getMobile());
            hOrgUser.setModifier(null);
            hOrgUser.setModifiedtime(new Date());
            hOrgUser.setName(userDetail.getName());
            hOrgUser.setOfficephone(userDetail.getTelephone());
            hOrgUser.setPassword(PASSWORD);
            hOrgUser.setPinyin(SynUserUtil.getPinyin(userDetail.getName()));
            hOrgUser.setPosition(userDetail.getTitle());
            hOrgUser.setPrivacylevel(null);
            hOrgUser.setRemarks(userDetail.getRemarks());
            hOrgUser.setSecretaryid(null);
            hOrgUser.setShortpinyin(SynUserUtil.getShortPinyin(userDetail.getName()));
            hOrgUser.setSortkey(ysUserSortKey);
            hOrgUser.setSourceid(userDetail.getUnionid());
            hOrgUser.setStatus(STATUS);
            hOrgUser.setUserid(userDetail.getUserId());
            hOrgUser.setUsername(userDetail.getUserId());
            // h_org_dept_user
            HOrgDeptUser hOrgDeptUser = new HOrgDeptUser();
            hOrgDeptUser.setCreatedtime(new Date());
            hOrgDeptUser.setCreater(null);
            hOrgDeptUser.setDeleted(false);
            hOrgDeptUser.setDeptid(deptId);
            hOrgDeptUser.setDeptsourceid(deptSourceId);
            hOrgDeptUser.setId(SynUserUtil.getUUID());
            hOrgDeptUser.setLeader(false);
            hOrgDeptUser.setModifiedtime(new Date());
            hOrgDeptUser.setModifier(null);
            hOrgDeptUser.setMain(false);
            hOrgDeptUser.setUsersourceid(userDetail.getUserId());
            // hOrgDeptUser.setUserid(ysUserId);
            hOrgDeptUser.setSortkey(ysUserSortKey.toString());
            hOrgDeptUser.setId(SynUserUtil.getUUID());
            // h_org_role_user
            List<Role> roles = deptUser.getRoles();
            HOrgRoleUser hOrgRoleUser = new HOrgRoleUser();
            if (!CollectionUtils.isEmpty(roles)) {
                for (Role role : roles) {
                    HOrgRole hOrgRole = new HOrgRole();
                    hOrgRole.setSourceid(role.getId());
                    String ysRloeId = hOrgRoleMapper.select(hOrgRole).get(0).getId();
                    hOrgRoleUser.setCreatedtime(new Date());
                    hOrgRoleUser.setCreater(null);
                    hOrgRoleUser.setDeleted(false);
                    hOrgRoleUser.setDeptid(deptId);
                    hOrgRoleUser.setId(SynUserUtil.getUUID());
                    hOrgRoleUser.setModifiedtime(new Date());
                    hOrgRoleUser.setRoleid(ysRloeId);
                    hOrgRoleUser.setRolesourceid(role.getId());
                    hOrgRoleUser.setUserid(ysUserId);
                    hOrgRoleUser.setUnittype(UNITTYPE);
                    hOrgRoleUser.setUsersourceid(userDetail.getUserId());
                }
            }
            HOrgUser user = new HOrgUser();
            user.setUserid(deptUser.getUserid());
            user.setCorpid(corpId);
            List<HOrgUser> hOrgUserList = hOrgUserMapper.select(user);
            if (CollectionUtils.isEmpty(hOrgUserList)) {// 无此人，新增
                hOrgUsers.add(hOrgUser);
                hOrgDeptUser.setUserid(ysUserId);// 为空设置userId为新生成的ysUserId
                // hOrgDeptUsers.add(hOrgDeptUser);
                if (!StringUtils.isEmpty(hOrgRoleUser.getId())) {
                    hOrgRoleUsers.add(hOrgRoleUser);
                }
            } else {
                // 不为空，取出该用户id
                hOrgDeptUser.setUserid(hOrgUserList.get(0).getId());
            }
            HOrgDeptUser orgDeptUser = new HOrgDeptUser();
            orgDeptUser.setUserid(hOrgDeptUser.getUserid());
            orgDeptUser.setDeptid(hOrgDeptUser.getDeptid());
            List<HOrgDeptUser> orgDeptUsers = hOrgDeptUserMapper.select(orgDeptUser);
            if (CollectionUtils.isEmpty(orgDeptUsers)) {
                // 多部门，每一次都插入
                hOrgDeptUsers.add(hOrgDeptUser);
            }
        }
        insertH_org_user(hOrgUsers);
        insertH_org_dept_user(hOrgDeptUsers);
        insertH_org_role_user(hOrgRoleUsers);
        long currentTimeMillis1 = System.currentTimeMillis();
        log.info("同步单个部门" + deptId + "耗时:" + (currentTimeMillis1 - currentTimeMillis) + "ms");
    }

    /**
     * @param hasMore
     * @param results
     * @param deptSourceId
     * @param req
     * @param client
     * @param appkey
     * @param appsecret
     * @return java.util.List<com.alibaba.fastjson.JSONObject>
     * @author liujing
     * @description: 递归获取部门下userList
     * @date 2021/5/24
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    public List<JSONObject> getList(Boolean hasMore, List<JSONObject> results, String deptSourceId,
        OapiIndustryUserListRequest req, DingTalkClient client, String appkey, String appsecret) throws ApiException {
        if (hasMore) {
            req.setDeptId(Long.parseLong(deptSourceId));
            req.setSize(1000L);
            OapiIndustryUserListResponse rsp = client.execute(req, getAccess_token(appkey, appsecret));
            log.info("请求钉钉返回部门信息---->>>" + rsp.toString());
            HashMap hashMap = JSON.parseObject(rsp.getBody(), HashMap.class);
            log.info("请求钉钉返回部门信息hashMap---->>>" + hashMap);
            if (0 != (int)hashMap.get("errcode")) {
                return null;
            }
            JSONObject jsonObject = (JSONObject)hashMap.get("result");
            // 获取用户list
            List<JSONObject> list = (List<JSONObject>)jsonObject.get("details");
            log.info("请求钉钉返回部门信息list---->>>" + list.toString());
            results.addAll(list);
            Boolean has_more = (Boolean)jsonObject.get("has_more");
            log.info("本次请求返回 has_more 的值为---->>>" + has_more);
            if (!has_more) {
                return results;
            } else {
                req.setCursor(req.getCursor() + req.getSize());
                getList(has_more, results, deptSourceId, req, client, appkey, appsecret);
            }
        }
        return results;
    }

    @SuppressWarnings("unused")
    @Transactional(rollbackFor = Exception.class)
    public void insertH_org_user(List<HOrgUser> hOrgUsers) {
        if (CollectionUtils.isEmpty(hOrgUsers)) {
            log.info("h_org_user暂无新增!");
            return;
        }
        log.info("h_org_user新增用户开始");
        int i = hOrgUserMapper.insertList(hOrgUsers);
        log.info("h_org_user新增了" + hOrgUsers.size() + "条数据");
    }

    @SuppressWarnings("unused")
    @Transactional(rollbackFor = Exception.class)
    public void insertH_org_role_user(List<HOrgRoleUser> hOrgRoleUsers) {
        if (CollectionUtils.isEmpty(hOrgRoleUsers)) {
            log.info("h_org_role_user暂无新增!");
            return;
        }
        log.info("h_org_role_user新增开始");
        int i = hOrgRoleUserMapper.insertList(hOrgRoleUsers);
        log.info("h_org_role_user新增了" + hOrgRoleUsers.size() + "条数据");
    }

    @SuppressWarnings("unused")
    @Transactional(rollbackFor = Exception.class)
    public void insertH_org_dept_user(List<HOrgDeptUser> hOrgDeptUsers) {
        if (CollectionUtils.isEmpty(hOrgDeptUsers)) {
            log.info("h_org_dept_user暂无新增!");
            return;
        }
        log.info("h_org_dept_user新增开始");
        int i = hOrgDeptUserMapper.insertList(hOrgDeptUsers);
        log.info("h_org_dept_user新增了" + hOrgDeptUsers.size() + "条数据");
    }

    /**
     * @param
     * @return java.lang.String
     * @author liujing
     * @description: getAccess_token
     * @date 2021/3/15
     */
    @SuppressWarnings("unchecked")
    public String getAccess_token(String appkey, String appsecret) throws ApiException {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/gettoken");
        OapiGettokenRequest request = new OapiGettokenRequest();
        request.setAppkey(appkey);
        request.setAppsecret(appsecret);
        request.setHttpMethod("GET");
        OapiGettokenResponse response = client.execute(request);
        // log.info("请求钉钉获取access_token返回信息---->>>"+response.toString());
        Map<String, Object> map = JSON.parseObject(response.getBody(), HashMap.class);
        // log.info("获取的access_token为———>>"+map.get("access_token"));
        return (String)map.get("access_token");
    }

    /**
     * @param userId
     * @return com.authine.cloudpivot.web.api.bean.UserDetail
     * @author liujing
     * @description: 根据userid获取用户详情
     * @date 2021/3/15
     */
    @SuppressWarnings("rawtypes")
    public UserDetail getUserDetail(String userId, String appkey, String appsecret) throws ApiException {
        DingTalkClient client = new DefaultDingTalkClient("https://oapi.dingtalk.com/topapi/v2/user/get");
        OapiV2UserGetRequest req = new OapiV2UserGetRequest();
        req.setUserid(userId);
        req.setLanguage("zh_CN");
        OapiV2UserGetResponse rsp = client.execute(req, getAccess_token(appkey, appsecret));
        // log.info("根据userid获取用户详情"+rsp.getBody());
        HashMap hashMap = JSON.parseObject(rsp.getBody(), HashMap.class);
        JSONObject jsonObject = (JSONObject)hashMap.get("result");
        UserDetail user = JSON.toJavaObject(jsonObject, UserDetail.class);
        return user;
    }

}
